package com.cqemme.activitiservice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cqemme.activitiservice.po.AlarmMessageInfo;
import com.cqemme.activitiservice.service.ListenerService;
import com.cqemme.activitiservice.service.MyHistoryService;
import com.cqemme.comm.constraint.MqNames;
import com.cqemme.comm.enums.AlarmType;
import com.cqemme.comm.enums.EnumActiviti;
import com.cqemme.comm.po.SendMessageParams;
import com.cqemme.comm.utils.JackSonUtils;
import com.cqemme.comm.utils.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.history.HistoricActivityInstance;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.util.*;

/**
 * @author nejery
 */
@Service
@Slf4j
public class ListenerServiceImpl implements ListenerService {

    @Resource
    private MyHistoryService myHistoryService;

    @Resource
    private AmqpTemplate amqpTemplate;

    @Override
    public void sendToSchoolSave(DelegateExecution execution) {
        AlarmMessageInfo alarmMessageInfo = new AlarmMessageInfo();
        String processInstanceId = execution.getProcessInstanceId();
        int msgType = Integer.parseInt(execution.getVariable("alarmType").toString());
        int orgCode = Integer.parseInt(execution.getVariable("orgCode").toString());
        alarmMessageInfo.setMessageType(msgType);
        alarmMessageInfo.setMsgContent(AlarmType.getcName(msgType));
        alarmMessageInfo.setOrgCode(orgCode);
        alarmMessageInfo.setUuKey(processInstanceId);
        Map<String,Object> extData = new HashMap<>(1);
        extData.put("alarmType",execution.getVariable("alarmType"));
        extData.put("alarmTypeName", AlarmType.getcName((Integer) execution.getVariable("alarmType")));
        extData.put("instanceId",processInstanceId);
        extData.put("alarmData", JackSonUtils.transJsonNode((String) execution.getVariable("alarmData")));
        alarmMessageInfo.setExtData(JackSonUtils.beanToString(extData));

        sendToRabbitMq(MqNames.SCHOOL_ALL_TO_SOCKET_SAVE_MESSAGE_INFO,alarmMessageInfo);
    }


    private  void sendToRabbitMq(String mqName, Object messageObject){
        log.info("========发送到消息队列 「{}」============", mqName);
        log.info(JackSonUtils.beanToString(messageObject));
        amqpTemplate.convertAndSend(mqName,JackSonUtils.beanToString(messageObject));

    }

    @Override
    public void sendNodeMessage(DelegateExecution execution) {
        String orgCode = execution.getVariable("orgCode").toString();
        //存节点描述
        String currentActivityId = execution.getCurrentActivityId();
        String nodeKey = currentActivityId + "_description";
        setVariable(execution,nodeKey,"已发送报警通知");
        Map map = getCurrentNodeBpmnVariables(execution);
        log.info("===节点参数为：====");
        log.info(JackSonUtils.beanToString(map));
        SendMessageParams sendMessageParams = new SendMessageParams();
        String processInstanceId = execution.getProcessInstanceId();
        sendMessageParams.setUuKey(processInstanceId);
        sendMessageParams.setOrgCode(Integer.parseInt(orgCode));
        Object sendMsg = map.get("sendMsg");
        if(null != sendMsg){
            try {
                sendMessageParams.setSendMsg(Integer.parseInt((String) sendMsg));
            }catch (Exception e){
                log.error("{}步骤中的sendMsg转换成数值异常，sendMsg={}",currentActivityId,sendMsg);
            }
        }
        // 发送给个人
        if (map.containsKey(EnumActiviti.SendPerson.getmText())) {
            // 发送给多人
            List<Long> res =  new ArrayList<>();
            String assignes = getLastNodeValue(execution, "_assign");
            if(null == assignes){
                log.error("没找到应该发给谁！----");
                return;
            }
            String[] split = assignes.split(",");
            for(String str :split){
                res.add(Long.parseLong(str));
            }
            sendMessageParams.setPhones(res);
        }
        // 发送给角色
        if (map.containsKey(EnumActiviti.SendRole.getmText())) {
            String o = (String) map.get(EnumActiviti.SendRole.getmText());
            String[] split = o.split(",");
            List<String> strings = Arrays.asList(split);
            sendMessageParams.setRoleCodes(strings);
            String nodeKey1 = currentActivityId + "_roles";
            setVariable(execution,nodeKey1,o);
        }

        // 发送给上一个节点选择的节点
        if(map.containsKey(EnumActiviti.SendRoleNext.getmText())){
            String  o = getLastNodeValue(execution, "_roles");
            String[] split = o.split(",");
            List<String> strings = Arrays.asList(split);
            sendMessageParams.setRoleCodes(strings);
            String nodeKey1 = currentActivityId + "_roles";
            setVariable(execution,nodeKey1,o);
        }
        sendToRabbitMq(MqNames.SCHOOL_ALL_TO_SOCKET_SEND_MESSAGE_INFO_BY_PARAMS,sendMessageParams);
    }

    @Override
    public void setVariable(DelegateExecution execution, String key, String value) {
        log.info("===== 自动节点设置变量:{}={}",key, value);
        execution.setVariable(key,value);
    }

    private void addToList(String str, List<Object> list){
        if( null != str){
            ArrayNode jsonNodes = JackSonUtils.transArrayNode(str);
            for(JsonNode jsonNode : jsonNodes){
                list.add(jsonNode);
            }

        }
    }

    @Override
    public Map getCurrentNodeBpmnVariables(DelegateExecution execution) {
        Map m = JSONObject.parseObject(JSONObject.toJSONString(execution.getCurrentFlowElement()), Map.class);
        List<Object> list = new ArrayList<>();
        if(null != m){
            Object flowElement = m.get("fieldExtensions");
            if(null != flowElement) {
                addToList(JackSonUtils.beanToString(flowElement),list);
            }
        }

        Map m1 = JSONObject.parseObject(JSONObject.toJSONString(execution.getCurrentActivitiListener()), Map.class);
        if(null != m1){
            Object listener = m1.get("fieldExtensions");
            if(null != listener){
                addToList(JackSonUtils.beanToString(listener),list);
            }
        }

        //得到参数和值数组
        //要推送消息的组织
        Map map = new HashMap<>();
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");

        /**
         * 无法使用java 很麻烦，是使用javascript；
         */
        try {
            engine.eval("function complete(str) {\n" +
                    "    var res = \"\";\n" +
                    "    try {\n" +
                    "        var parse = JSON.parse(str);\n" +
                    "        var tempObj = {};\n" +
                    "        if(parse instanceof Array){\n" +
                    "            for(var i=0; i<parse.length; i++){\n" +
                    "                tempObj[parse[i].fieldName] = parse[i].stringValue;\n" +
                    "            }\n" +
                    "        }\n" +
                    "        res = JSON.stringify(tempObj);\n" +
                    "    }catch (e) {\n" +
                    "        res = \"\";\n" +
                    "    }\n" +
                    "    return res;\n" +
                    "}");
            if (engine instanceof Invocable) {
                Invocable in = (Invocable) engine;

                log.info("节点扩展字段：{}",execution.getCurrentActivityId());
                log.info(JackSonUtils.beanToString(list));
                String res = (String) in.invokeFunction("complete", JackSonUtils.beanToString(list));
                map = JackSonUtils.strToBean(res, Map.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    @Override
    public String getLastNodeValue(DelegateExecution execution, String endFix) {
        String res = null;
        List<HistoricActivityInstance> historicActivityInstances = myHistoryService.selectHistoryNode(execution.getProcessInstanceId());
        String values;
        if(historicActivityInstances.size() > 0){
            HistoricActivityInstance historicActivityInstance;
            for(int i = historicActivityInstances.size()-1; i>0; i--){
                historicActivityInstance = historicActivityInstances.get(i);
                values = (String) execution.getVariable(historicActivityInstance.getActivityId()+endFix);
                if(null != values){
                    res = values;
                    break;
                }
            }
        }else{
            // 流程未启动, 暂时没有流程节点
            Map<String, Object> variables = execution.getVariables();
            for(String str : variables.keySet()){
                if(str.contains(endFix)){
                    res = (String) variables.get(str);
                    break;
                }
            }
        }
        return res;
    }

    @Override
    public void repeatSendMessage(DelegateExecution execution) {
        String currentActivityId = execution.getCurrentActivityId();
        Object timesObject = execution.getVariable(currentActivityId + "_times");
        Map currentNodeBpmnVariables = getCurrentNodeBpmnVariables(execution);
        int times = 1;
        if(null != timesObject){
            times = Integer.parseInt((String) timesObject);
            times = ++times;
        }
        Object o = currentNodeBpmnVariables.get("times_" + times);
        String durations = "PT90000M";
        if(null != o){
            durations = (String) o;
        }
        setVariable(execution,currentActivityId + "_times",String.valueOf(times));
        setVariable(execution,currentActivityId+"_timer", durations);
    }
}
